/**
 ** 指令缓冲区，可容纳64条指令
**/
module instCache (
    input wire clk,
    input wire rst,
    input wire [11:0] pc_1, pc_2,
    output reg load_over,
    output reg [31:0] inst_one, inst_two  //每个时钟向外输出两条指令
);
    //链接RAM的接口信号
    /* 1. ID branch */
    wire           if_jump = 0;
    wire [31:0]    prdt_pc_add_op1 = 0;
    wire [31:0]    prdt_pc_add_op2 = 0;
    
    /* 2. L/S instr */
    wire           d_hready = 1;
    
    /* 3. DIV instr */
    wire           div_alu_time = 0;
    
    /* 4. data hazard */
    wire           wr_stop = 0;
    
    /* 5. interrupt  */
    wire  [31:0] normal_PC;
    wire           trap_entry_en = 0;
    wire           trap_exit_en = 0;
    wire [31:0]    trap_entry_pc = 0;
    wire [31:0]    restore_pc = 0;
    
    /* 5. ahb master */
    wire         i_hbusreq;
    wire [1:0]    i_htrans; /* IDLE, NONSEQ */
    wire [31:0]   i_haddr;
    wire          i_hwrite;
    wire [63:0]   i_hwdata;
    wire [2:0]    i_hsize; /* 3'b011 */
    wire [2:0]    i_hburst;/* 3'b000 */
    wire [2:0]    i_hprot;/* 3'b010 */
    wire           i_hgrant;
    wire           i_hready;
    wire  [1:0]    i_hresp; 
    wire [63:0]    i_hrdata;
    
    wire [31:0] instr1;
    wire instr1_vld;
    wire [31:0] instr2;
    wire instr2_vld;

    //存储指令的数组
    reg [31:0] insts [0:63];
    reg [5:0] index; 

    initial begin
        //初始化加载完成标志位
        load_over = 0;
        //初始化下标
        index = 0;
    end

    //实例化总线和RAM
    ITCM_top u_ITCM(
        .clk(clk),
        .rst_n(~rst),
        
        .i_hsel(1'b1),
        .i_hwrite(1'b0),
        .i_haddr(i_haddr),
        .i_htrans(i_htrans),
        .i_hready(i_hready),
        .i_hresp(i_hresp),
        .i_hrdata(i_hrdata)
        
    );

     ahb_arbiter u_ahb_arbiter(
            .clk(clk),
            .rst_n(~rst),
            
            .i_hbusreq(i_hbusreq),
            .i_hgrant(i_hgrant),    
            
            .i_hresp(i_hresp),
            .i_hready(i_hready),
            
            .d_hbusreq(1'b0),
            .d_hgrant(),
            
            .d_hresp('d0),
            .d_hready('d0)    
    );

    IF2ITCM u_if(
                    .clk(clk),
                    .rst_n(~rst),
        
        /* 1. ID branch */
                    .if_jump(if_jump),
                    .prdt_pc_add_op1(normal_PC),
                    .prdt_pc_add_op2('d1),
        
        /* 2. L/S instr */
                    .d_hready(d_hready),
        
        /* 3. DIV instr */
                    .div_alu_time(div_alu_time),
        
        /* 4. data hazard */
                    .wr_stop(wr_stop),
        
        /* 5. interrupt  */
                    .normal_PC(normal_PC),
                    .trap_entry_en(trap_entry_en),
                    .trap_exit_en(trap_exit_en),
                    .trap_entry_pc(trap_entry_pc),
                    .restore_pc(restore_pc),
        
        /* 5. ahb master */
                    .i_hbusreq(i_hbusreq),
                    .i_htrans(i_htrans), /* IDLE(), NONSEQ */
                    .i_haddr(i_haddr),
                    .i_hwrite(i_hwrite),
                    .i_hwdata(i_hwdata),
                    .i_hsize(i_hsize), /* 3'b011 */
                    .i_hburst(i_hburst),/* 3'b000 */
                    .i_hprot(i_hprot),/* 3'b010 */
                    .i_hgrant(i_hgrant),
                    .i_hready(i_hready),
                    .i_hresp(i_hresp),
                    .i_hrdata(i_hrdata),
        
                    .instr1(instr1),
                    .instr1_vld(instr1_vld),
                    .instr2(instr2),
                    .instr2_vld(instr2_vld)   
    );

    initial begin
        load_over = 1;
        index = 48;
        //初始化指令
        insts[0] = 32'b00000000000011000000001010000001;
        insts[1] = 32'b00000000000000011100010000000001;
        insts[2] = 32'b00000000000100011001000010000001;
        insts[3] = 32'b00000000000001011100001000000001;
        insts[4] = 32'b00000000000000001010010010000001;
        insts[5] = 32'b00000000000000001100000100000001;
        insts[6] = 32'b00000000000010111110001110000001;
        insts[7] = 32'b00000000000000100000100000000001;
        insts[8] = 32'b00000000000001011100101010000001;
        insts[9] = 32'b00000000000101001001100100000001;
        insts[10] = 32'b00000000000110001000010100000001;
        insts[11] = 32'b00000000000000011111111100000001;
        insts[12] = 32'b00000010100000101000000010110011;
        //insts[12] = 32'b00000000010101001000001010110011;
        insts[13] = 32'b00000000010000001000000010110011;
        insts[14] = 32'b00000000010101001000001010110011;
        insts[15] = 32'b00000010010101000000001010110011;
        insts[16] = 32'b00000010001000101000000100110011;
        insts[17] = 32'b00000000100100010000000100110011;
        insts[18] = 32'b00000000000100111000100000110011;
        insts[19] = 32'b00000000000100111000100000110011;
        insts[20] = 32'b00000000000101001000001110110011;
        insts[21] = 32'b00000001001010101000001110110011;
        insts[22] = 32'b00000000011101010000010000110011;
        insts[23] = 32'b00000001111010010000010100110011;
        insts[24] = 32'b00000010100000101000000010110011;
        insts[25] = 32'b00000000010000001000000010110011;
        insts[26] = 32'b00000000010101001000001010110011;
        insts[27] = 32'b00000010010101000000001010110011;
        insts[28] = 32'b00000010001000101000000100110011;
        insts[29] = 32'b00000000100100010000000100110011;
        insts[30] = 32'b00000000000100111000100000110011;
        insts[31] = 32'b00000000000100111000100000110011;
        insts[32] = 32'b00000000000101001000001110110011;
        insts[33] = 32'b00000001001010101000001110110011;
        insts[34] = 32'b00000000011101010000010000110011;
        insts[35] = 32'b00000001111010010000010100110011;
        insts[36] = 32'b00000010100000101000000010110011;
        insts[37] = 32'b00000000010000001000000010110011;
        insts[38] = 32'b00000000010101001000001010110011;
        insts[39] = 32'b00000010010101000000001010110011;
        insts[40] = 32'b00000010001000101000000100110011;
        insts[41] = 32'b00000000100100010000000100110011;
        insts[42] = 32'b00000000000100111000100000110011;
        insts[43] = 32'b00000000000100111000100000110011;
        insts[44] = 32'b00000000000101001000001110110011;
        insts[45] = 32'b00000001001010101000001110110011;
        insts[46] = 32'b00000000011101010000010000110011;
        insts[47] = 32'b00000001111010010000010100110011;
    end

    // always @(posedge clk) begin
    //     if (instr1==32'h00000013 || instr2==32'h00000013) begin
    //         //指令读取结束
    //         load_over = 1;
    //     end
    //     else begin
    //         //指令读取过程中，使能位拉高，读取指令进cache
    //         if (instr1_vld) begin
    //             insts[index] = instr1;
    //             //$display("下标: ", index, "指令: %h", insts[index]);
    //             index = index+1;
    //         end

    //         if (instr2_vld) begin
    //             insts[index] = instr2;
    //             //$display("下标: ", index, " 指令: %h", insts[index]);
    //             index = index+1;
    //         end
    //     end
    // end

    //每次输出两条指令
    always @(posedge clk) begin
        if (load_over) begin
            if (pc_1<index && pc_2<index) begin
                inst_one <= insts[pc_1];
                inst_two <= insts[pc_2];
            end
            else begin
                inst_one <= 32'h00000000;
                inst_two <= 32'h00000000;
            end
        end
    end
    
endmodule